#include "StrategyCodec.h"
#include "strategies/RandomKnockingStrategy.h"
#include "strategies/RandomDrawingStrategy.h"
#include "strategies/RandomDiscardStrategy.h"
#include "strategies/MaxScoreDiscardStrategy.h"
#include "strategies/ExpValueDrawingStrategy.h"
#include "strategies/OptimisticDrawingStrategy.h"
#include "strategies/PessimisticDrawingStrategy.h"
#include "strategies/VariableRandomKnockingStrategy.h"
#include "strategies/PointThresholdKnockingStrategy.h"
#include "strategies/TurnThresholdKnockingStrategy.h"
#include "strategies/OppSuitTrackDiscardStrategy.h"
#include "strategies/MinOppGainDiscardStrategy.h"
#include "strategies/PointIncProbKnockingStrategy.h"
#include "strategies/PointBracketingKnockingStrategy.h"
#include "strategies/SimEVDiscardStrategy.h"
#include "strategies/PointIncProbDrawingStrategy.h"
#include "strategies/MaxMinDiscardStrategy.h"
#include "strategies/SimpleDrawingStrategy.h"
#include "strategies/SimEVKnockingStrategy.h"

void StrategyCodec::fillRegistry() {
    // Implemented knocking strategies
    strategyRegistry[KNOCKING][0] = dynamic_cast<Strategy*>(new RandomKnockingStrategy());
    strategyRegistry[KNOCKING][1] = dynamic_cast<Strategy*>(new VariableRandomKnockingStrategy());
    strategyRegistry[KNOCKING][2] = dynamic_cast<Strategy*>(new PointThresholdKnockingStrategy());
    strategyRegistry[KNOCKING][3] = dynamic_cast<Strategy*>(new TurnThresholdKnockingStrategy());
    strategyRegistry[KNOCKING][4] = dynamic_cast<Strategy*>(new PointIncProbKnockingStrategy());
    strategyRegistry[KNOCKING][5] = dynamic_cast<Strategy*>(new PointBracketingKnockingStrategy());
    strategyRegistry[KNOCKING][6] = dynamic_cast<Strategy*>(new SimEVKnockingStrategy());
    // Implemented drawing strategies
    strategyRegistry[DRAWING][0] = dynamic_cast<Strategy*>(new RandomDrawingStrategy());
    strategyRegistry[DRAWING][1] = dynamic_cast<Strategy*>(new ExpValueDrawingStrategy());
    strategyRegistry[DRAWING][2] = dynamic_cast<Strategy*>(new OptimisticDrawingStrategy());
    strategyRegistry[DRAWING][3] = dynamic_cast<Strategy*>(new PessimisticDrawingStrategy());
    strategyRegistry[DRAWING][4] = dynamic_cast<Strategy*>(new PointIncProbDrawingStrategy());
    strategyRegistry[DRAWING][5] = dynamic_cast<Strategy*>(new SimpleDrawingStrategy());
    //Implemented discard strategies
    strategyRegistry[DISCARD][0] = dynamic_cast<Strategy*>(new RandomDiscardStrategy());
    strategyRegistry[DISCARD][1] = dynamic_cast<Strategy*>(new MaxScoreDiscardStrategy());
    strategyRegistry[DISCARD][2] = dynamic_cast<Strategy*>(new OppSuitTrackDiscardStrategy());
    strategyRegistry[DISCARD][3] = dynamic_cast<Strategy*>(new MinOppGainDiscardStrategy());
    strategyRegistry[DISCARD][4] = dynamic_cast<Strategy*>(new SimEVDiscardStrategy());
    strategyRegistry[DISCARD][5] = dynamic_cast<Strategy*>(new MaxMinDiscardStrategy());
}

StrategyGene* StrategyCodec::encode(StrategyType type, int index) const {
    if (type == END_DRAW) type = DRAWING;
    else if (type == END_DISCARD) type = DISCARD;
    Strategy* strategyClass = strategyRegistry[type][index];
    return new StrategyGene(strategyClass->getName(), strategyClass->getNumParameters());
}

Strategy* StrategyCodec::decode(StrategyType type, StrategyGene* gene) const {
    Strategy* ret = NULL;
    string strategyName = gene->getStrategyName();
    for (int i = 0; i < AVAILABLE_STRATEGIES[type]; i++) {
        if (strategyRegistry[type][i]->getName() == strategyName) {
            ret = strategyRegistry[type][i]->getActiveInstance(gene->getWeight());
            for (int j = 0; j < gene->getParametersSize(); j++) {
                ret->setExecutionParameter(j, gene->getParameter(j));
            }
            break;
        }
    }
    return ret;
}

